// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 由addchain生成的代码。不要编辑。

package fiat

// 反转设置e=1/x，并返回e。
// 
// 如果x=0，则反转返回e=0。
func (e *P521Element) Invert(x *P521Element) *P521Element {
	// 反转是以指数p的幂运算实现的− 2.
	// 13次乘法和520次平方运算的序列来自于使用github生成的
	// 以下加法链。com/mmcloughlin/addchain v0。3.0. 
	// 
	// U 10=2*1 
	// U 11=1+/U 10 
	// U 1100=U 11<2 
	// U 1111=U 11+U 1100 
	// U 11110000=U 1111<4 
	// U 11111=U 1111+U 1111+U 1111+U 11110 
	// x16=
	// x65=2*x64+1 
	// x129=x65<64+x64 
	// x130=2*x129+1 
	// x259=x130<129+x129 

	var z = new(P521Element).Set(e)
	var t0 = new(P521Element)

	z.Square(x)
	z.Mul(x, z)
	t0.Square(z)
	for s := 1; s < 2; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	for s := 1; s < 4; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	for s := 1; s < 8; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	for s := 1; s < 16; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	for s := 1; s < 32; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	t0.Mul(x, t0)
	for s := 0; s < 64; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	t0.Mul(x, t0)
	for s := 0; s < 129; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	t0.Square(z)
	t0.Mul(x, t0)
	for s := 0; s < 259; s++ {
		t0.Square(t0)
	}
	z.Mul(z, t0)
	for s := 0; s < 2; s++ {
		z.Square(z)
	}
	z.Mul(x, z)

	return e.Set(z)
}
